登录注册页使用独立布局(SinglePage),不包含系统默认的 Header 组件,因此国际化切换和暗黑模式切换按钮需要单独集成到登录页面中。同时,登录页不应出现在系统菜单列表中,需要通过路由 meta 的 hideMenu 属性来控制其可见性。
集成国际化与暗黑模式切换
之前在 Header 组件中已经实现了暗黑模式切换(AutoToggle)和国际化切换(ChangeLocale)两个组件。在 SinglePage 布局中复用这些组件非常简单,只需将它们放置在页面的固定位置:
<!-- layouts/SinglePage.vue -->
<template>
<div class="h-screen">
<!-- 右上角固定位置:语言切换 + 暗黑模式 -->
<div class="fixed right-2.5 top-0 z-50 flex items-center">
<ChangeLocale :locales="locales" @change="handleLocaleChange" />
<AutoToggle />
</div>
<!-- 页面内容 -->
<router-view />
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import ChangeLocale from '~/components/Header/ChangeLocale.vue'
import AutoToggle from '~/components/Header/AutoToggle.vue'
const locales = ref([
{ label: '简体中文', value: 'zh-CN' },
{ label: 'English', value: 'en' },
])
const handleLocaleChange = async (locale: string) => {
const { loadLocaleMessages } = useI18n()
await loadLocaleMessages(locale)
}
</script>
vue
这里将两个功能按钮放在 position: fixed; right: 10px; top: 0 的位置,使用 flex 布局居中对齐,确保它们浮动在登录表单的右上角,不干扰主要内容的展示。
国际化切换逻辑
ChangeLocale 组件接收一个 locales 数组作为 prop,包含所有支持的语言选项。当用户切换语言时,触发 change 事件,在父组件中调用 loadLocaleMessages 动态加载对应的语言包。
locales 数组目前在 SinglePage 中直接定义,后续可以提取为全局配置项:
// 未来可提取为全局配置
// config/i18n.ts
export const SUPPORTED_LOCALES = [
{ label: '简体中文', value: 'zh-CN' },
{ label: 'English', value: 'en' },
]
typescript
路由 meta 控制菜单隐藏
当为登录页面设置了 title 后,系统菜单中会自动出现"登录注册页"这个菜单项。这显然不是期望的行为。解决方法是在路由 meta 中添加 hideMenu 属性:
// router/routes.ts
{
path: '/login',
name: 'Login',
component: () => import('~/pages/login/index.vue'),
meta: {
layout: 'SinglePage',
hideMenu: true, // 关键:不在菜单中显示
title: '登录注册页',
},
}
typescript
在菜单渲染逻辑中,通过检查 route.meta.hideMenu 来过滤掉不需要显示的页面:
<!-- 侧边栏菜单渲染逻辑 -->
<template v-for="route in menuRoutes" :key="route.path">
<el-menu-item
v-if="!route.meta?.hideMenu"
:index="route.path"
>
{{ route.meta?.title }}
</el-menu-item>
</template>
vue
// 过滤隐藏菜单项
const menuRoutes = computed(() => {
return routes.filter(route => !route.meta?.hideMenu)
})
typescript
完整的 SinglePage 布局
将上述功能整合到 SinglePage 布局中:
<!-- layouts/SinglePage.vue -->
<template>
<div class="h-screen flex items-center justify-center">
<!-- 右上角功能按钮 -->
<div class="fixed right-2.5 top-0 z-50 flex items-center gap-2">
<ChangeLocale :locales="locales" @change="handleLocaleChange" />
<AutoToggle />
</div>
<!-- 主内容区域 -->
<div class="w-full max-w-md">
<router-view />
</div>
</div>
</template>
vue
总结
登录注册页的国际化切换和暗黑模式集成并不复杂,核心是复用 Header 组件中已有的子组件。关键点有两个:一是将功能按钮放在 fixed 定位的右上角位置,二是通过路由 meta 的 hideMenu 属性避免登录页出现在系统导航菜单中。这种 meta 驱动的配置方式是 Vue Router 中控制页面行为的常见模式,在权限控制、布局切换等场景中同样适用。
↑